import { mapGetters } from 'vuex'
import SparkMD5 from 'spark-md5'
import ImagePreview from '@/components/ImagePreview'
import { downloadFile } from '@/utils/file'
export default {
  computed: {
    ...mapGetters(['token']),
  },
  components: {
    ImagePreview,
  },
  data() {
    return {
      // 表单项类型枚举
      formItemType: {
        SELECT: 'select', // 下拉框
        RADIO: 'radio', // 单选框
        INPUT: 'input', // 输入框
        TEXTAREA: 'textarea', // 文本域
        NUMBER: 'number', // 数字框
        IMAGE: 'image', // 图片上传
        FILE: 'file', // 大文件上传
        MARKDOWN: 'markdown', // markdown
        TREE: 'tree', // 树形下拉框
        TIME: 'time', // 时间
        CUSTOM: 'custom', // 自定义
      },
      // 表格列类型
      tableColumnType: {
        TEXT: 'text', // 文本类型
        TAG: 'tag', // 标签类型
        ICON: 'icon', // 图标
        IMAGE: 'image', // 图片类型
        CUSTOM: 'custom', // 自定义列
      },
      // 弹窗类型
      dialogType: {
        INSERT: '新增', // 新增
        UPDATE: '修改', // 修改
        DETAIL: '详情', // 详情
      },
      // 弹窗显示
      dialogFormVisible: false,
      // 当前弹窗类型
      currentDialogType: '',
      // 表格数据集合
      tableData: [],
      // 分页参数
      pageObj: {
        current: 1,
        size: 10,
      },
      // 表单查询数据
      formData: {},
      // 当前点击的表格数据
      currentTableColumn: {},
      // 总数
      dataTotal: 0,
      // 表格操作列配置
      optionColumnConfig: {
        // 按钮长度
        buttonWidth: 110,
        // 操作列长度
        optionColumnWidth: 210,
      },
      // 操作的表单数据
      optionFormData: {},
      // 当前表格选中的ID
      currentTableSelectIds: [],
      // 当前按钮显示总数
      currentButtonCount: 4,
      // 文件ID
      currentFileId: undefined,
      // 文件上传参数
      options: [],
      // 文件上传状态
      fileStatusText: {
        success: '上传成功!',
        error: '上传失败!',
        uploading: '上传中...',
        paused: '暂停',
        waiting: '等待上传...',
      },
      // 操作按钮加载
      optionButtonLoading: false,
    }
  },
  // 父组件传递参数
  props: {
    /**
     * 主题
     */
    title: String,
    /**
     * 表单按钮控制
     */
    formButtonCtl: Object,
    /**
     * 表单列表
     */
    formList: Array,
    /**
     *弹框大小
     */
    dialogWidth: Number,
    /**
     * 表单校验
     */
    formRules: Object,
    /**
     * 查询请求的store方法路径
     */
    selectUrl: String,
    /**
     * 新增请求的store方法路径
     */
    insertUrl: String,
    /**
     * 修改数据的store方法路径
     */
    updateUrl: String,
    /**
     * 删除数据的store方法路径
     */
    deleteUrl: String,
    /**
     * 详情请求的store方法路径
     */
    detailUrl: String,
    /**
     * 导出Excel的网络请求路径
     */
    exportExcelUrl: String,
    /**
     * 导入Excel的网络请求路径
     */
    importExcelUrl: String,
    /**
     * 表格列名集合
     */
    tableColumns: Array,
    /**
     * 表格其余宽度占比
     */
    tableLeftWidth: {
      type: Number,
      default: 0,
    },
    /**
     * 表格操作列最大按钮个数
     */
    maxOptionButtonCount: {
      type: Number,
      default: 4,
    },
    /**
     * 提示映射
     */
    tipMap: Map,
    /**
     * 插入或修改方法扩展
     */
    insertUpdateMethodExtend: Function,

    /**
     * 查询方法扩展(修改条件)
     */
    selectMethodExtend: Function,

    /**
     * 对表格数据的前置处理
     */
    selectDataExtend: Function,
    /**
     * 文件索引名称
     */
    fileIndex: String,
    /**
     * 弹窗宽度百分比
     */
    dialogWidth: Number,

    /**
     * 打开弹窗方法扩展
     */
    openDialogMethodExtend: Function,
    /**
     * 弹窗标签宽度
     */
    dialogLabelWidth: Number,

    /**
     * 获取表格选中的ID集合
     */
    getTableSelectIds: Function,
  },
  created() {
    this.selectMethod()
    this.initUpload()
  },
  mounted() {
    this.setOptionColumnWidth()
  },
  methods: {
    // 条件查询数据逻辑
    selectMethod(formData) {
      // 查询扩展
      if (this.selectMethodExtend != undefined) {
        try {
          formData = this.selectMethodExtend(formData)
        } catch (error) {
          this.$message({
            type: 'warning',
            message: error.message,
            showClose: true,
          })
        }
      }
      var pagination = this.formButtonCtl.pagination
      if (typeof pagination === 'undefined' || pagination) {
        formData = { ...formData, ...this.pageObj }
      }
      console.log(formData)

      this.$store.dispatch(this.selectUrl, formData).then((response) => {
        var data = response.data
        // 数据处理
        if (this.selectDataExtend != undefined) {
          data = this.selectDataExtend(data)
        }
        this.tableData = data // 数据
        console.table(data)
        if (!response.other) {
          return
        }
        this.dataTotal = parseInt(response.other.pageSize) // 分页总数
      })
    },
    // 初始化表单数据
    initSubmitData(type, data) {
      switch (type) {
        // 新增
        case this.dialogType.INSERT:
          this.optionFormData = {}
          break
        // 修改
        case this.dialogType.UPDATE:
          this.optionFormData = data
          break
        // 详情
        case this.dialogType.DETAIL:
          if (this.detailUrl == undefined) {
            this.optionFormData = data
          } else {
            this.detailMethod(data)
          }
          break
      }
      // 更新当前弹窗类型
      this.currentDialogType = type
      // 打开弹窗扩展
      if (this.openDialogMethodExtend != undefined) {
        try {
          this.openDialogMethodExtend(type, data)
        } catch (error) {
          this.$message({
            type: 'warning',
            message: error.message,
            showClose: true,
          })
          return
        }
        this.optionFormData = data
      }
      // 显示弹窗
      this.dialogFormVisible = true
    },
    // 详情
    detailMethod(data) {
      this.$store.dispatch(this.detailUrl, data).then((response) => {
        // 初始化表单数据
        this.optionFormData = response.data
      })
    },
    // 新增/修改数据逻辑
    insertUpdateMethod(type, data) {
      // 请求路径
      var requestUrl = this.insertUrl
      // 反馈信息
      var message = '新增'
      // 判断业务类型
      switch (type) {
        // 更新
        case this.dialogType.UPDATE:
          requestUrl = this.updateUrl
          message = '修改'
          break
        default:
          break
      }
      // 文件处理
      if (this.currentFileId && this.fileIndex) {
        data[this.fileIndex] = this.currentFileId
        this.currentFileId = undefined
      }
      // 扩展方法
      if (this.insertUpdateMethodExtend) {
        try {
          data = this.insertUpdateMethodExtend(data)
        } catch (error) {
          this.$message({
            type: 'warning',
            message: error.message,
            showClose: true,
          })
          return
        }
      }
      this.$refs.ruleForm.validate((valid) => {
        if (valid) {
          this.optionButtonLoading = true
          // 发起请求
          this.$store.dispatch(requestUrl, data).then((response) => {
            // 反馈消息
            if (response.success) {
              this.$message({
                type: 'success',
                message: `${message}${this.title}成功!`,
                showClose: true,
              })
              // 回显数据
              this.selectMethod()
            }
          })
        }
      })
      this.optionButtonLoading = false
    },
    // 删除数据逻辑
    deleteDataMethod(ids) {
      // 传入的数据为空
      if (ids == undefined || ids == null || ids == '') {
        this.$message({
          type: 'warning',
          message: `未选中任何${this.title}!`,
          showClose: true,
        })
        return
      }
      // 数组类型
      if (ids instanceof Array && ids.length < 1) {
        this.$message({
          type: 'warning',
          message: `请选择至少一个${this.title}!`,
          showClose: true,
        })
        return
      }
      this.$confirm(`此操作将直接删除选中的${this.title}, 是否继续?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        this.$store.dispatch(this.deleteUrl, ids).then((response) => {
          // 反馈
          if (response.success) {
            this.$message({
              type: 'success',
              message: `已成功删除${ids instanceof Array ? ids.length : 1}条${this.title}数据!`,
              showClose: true,
            })
            this.selectMethod()
          }
        })
      })
    },
    // 导出Excel
    exportExcelMethod() {
      if (!this.exportExcelUrl) {
        console.error('请设置导出Excel的请求地址!')
        return
      }
      //https://blog.csdn.net/kaimo313/article/details/117476200
      this.$store.dispatch('excel/exportExcel', this.exportExcelUrl).then((response) => {
        const link = document.createElement('a') // 创建元素
        console.log('获取的数据============>', response)
        let blob = new Blob([response.data], { type: 'application/x-download' })
        link.style.display = 'none'
        link.href = URL.createObjectURL(blob) // 创建下载的链接
        var fileName = decodeURI(response.headers['content-disposition'].split('filename=')[1])
        link.setAttribute('download', fileName) // 给下载后的文件命名
        document.body.appendChild(link)
        link.click() // 点击下载
        document.body.removeChild(link) //  下载完成移除元素
        window.URL.revokeObjectURL(link.href) // 释放掉blob对象
      })
    },
    // 导入Excel
    importExcelMethod(event, file, fileList) {
      if (!this.importExcelUrl) {
        console.error('请设置导入Excel的请求地址!')
        return
      }
      if (file == null) {
        return
      }
      this.$store.dispatch('excel/importExcel', { url: this.importExcelUrl, file: file }).then((response) => {
        if (response.success) {
          this.$message({
            type: 'success',
            message: `导入成功!`,
            showClose: true,
          })
          this.selectMethod()
        }
      })
    },
    // 上传文件
    uploadFile(event, file, fileList) {
      if (file == null) {
        return
      }
      this.$store.dispatch('file/uploadFile', file).then((response) => {
        if (response.success) {
          this.currentFileId = response.data
        }
      })
    },
    // 获取显示的按钮数并动态调整该列的宽度
    setOptionColumnWidth() {
      var buttonCount = this.maxOptionButtonCount
      // 判断传入的属性
      if (this.formButtonCtl) {
        // 遍历对象属性
        for (var key in this.formButtonCtl) {
          // 排除新增按钮
          if (key == 'insertButton') {
            continue
          }
          // 属性值为false证明按钮被隐藏
          if (!this.formButtonCtl[key]) {
            buttonCount--
          }
        }
      }
      this.currentButtonCount = buttonCount
      // 长度=按钮个数*单个按钮的长度
      this.optionColumnConfig.optionColumnWidth = this.optionColumnConfig.buttonWidth * (buttonCount - 1)
    },
    //  更改每页大小
    changePageSize(val) {
      this.pageObj.size = val
      this.selectMethod(this.formData)
    },
    //获取行Key
    getRowKey(row) {
      return row.id
    },
    //  更改当前显示页码
    changeCurrentPage(val) {
      this.pageObj.current = val
      this.selectMethod(this.formData)
    },
    //  筛选方法
    filterMethod(value, row, column) {
      return row[column['property']] === value
    },

    //当前点击的行
    currentColumnClick(row, column, event) {
      this.currentTableColumn = row
    },
    //  获取表格多选
    getIdsForCheckBox(val) {
      this.currentTableSelectIds = val.map((v) => {
        return v.id
      })
      // 回调
      if (this.getTableSelectIds != undefined) {
        this.getTableSelectIds(this.currentTableSelectIds)
      }
    },
    // 筛选数据格式转换
    coverFilters(obj) {
      var source = obj.filters
      if (!source || source.length === 0) {
        return
      }
      var list = source.map((v) => {
        return {
          text: v['filterName' in obj ? obj.filterName : 'title'],
          value: v['filterName' in obj ? obj.filterName : 'name'],
        }
      })
      return list
    },
    // 下载文件
    downloadFile,
    // markdown上传文件
    markdownUploadFile(event, insertImage, files) {
      if (files == null || files.length < 1) {
        return
      }
      this.$store.dispatch('file/uploadFile', files[0]).then((response) => {
        if (response.success) {
          insertImage({
            url: this.downloadFile(response.data),
            desc: response.data,
          })
        }
      })
    },
    // 初始化上传插件
    initUpload() {
      this.options = {
        target: '/api/fileService/file/chunk',
        testChunks: true,
        chunkSize: 2 << 20, // 2MB
        simultaneousUploads: 5, // 并发上传数
        maxChunkRetries: 3, // 最大自动失败重试上传次数
        fileParameterName: 'file',
        headers: {
          Authorization: this.token,
        },
        // 校验已上传的块
        checkChunkUploadedByResponse: function (chunk, message) {
          let objMessage = JSON.parse(message)
          //  获取当前的上传块的集合
          let chunkNumbers = objMessage.data
          //  判断当前的块是否被该集合包含，从而判定是否需要跳过
          return (chunkNumbers || []).indexOf(chunk.offset + 1) >= 0
        },
      }
    },
    // 完成上传
    onFileSuccess(rootFile, file, response, chunk) {
      let res = JSON.parse(response)
      // 文件已存在，直接调用回调函数
      if (res.status == 200 && typeof res.data[0].length >= 16) {
        // 执行回调函数
        this.$emit('doneBlock', res)
        this.currentFileId = res.data[0]
      }
      //  需要合并
      else if (res.status == 205) {
        const formData = new FormData()
        formData.append('identifier', file.uniqueIdentifier)
        formData.append('filename', file.name)
        formData.append('totalSize', file.size)
        formData.append('totalChunks', file.chunks.length)
        var message = this.$message({
          message: '正在合并文件，请稍后...',
          type: 'info',
          duration: 0,
        })
        this.$store.dispatch('file/mergeFile', formData).then((res) => {
          this.currentFileId = res.data
          message.close()
          this.$message({
            message: '合并完成,文件上传完毕!',
            type: 'success',
            showClose: true,
          })
          // 执行回调函数
          this.$emit('doneBlock', res.data)
        })
      } else {
        this.$message({
          message: res.message,
          type: 'error',
        })
      }
    },
    //  文件添加
    filesAdded(file, event) {
      this.computeMD5(file)
    },
    //重置条件
    refreshData() {
      this.formData = {}
      this.$refs.dataTable.clearSelection()
    },
    //  计算MD5
    computeMD5(file) {
      var message = this.$message({
        message: '正在计算MD5，请稍后...',
        type: 'info',
        duration: 0,
      })
      let fileReader = new FileReader()
      let time = new Date().getTime()
      let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
      let currentChunk = 0
      const chunkSize = 5 << 30 // 5MB
      let chunks = Math.ceil(file.size / chunkSize)
      let spark = new SparkMD5.ArrayBuffer()
      file.pause()
      loadNext()
      fileReader.onload = (e) => {
        spark.append(e.target.result)
        if (currentChunk < chunks) {
          currentChunk++
          loadNext()
          //  实时展示MD5的计算进度
          this.$nextTick(() => {
            console.log('校验MD5 ' + ((currentChunk / chunks) * 100).toFixed(0) + '%')
          })
        } else {
          let md5 = spark.end()
          this.computeMD5Success(md5, file)
          console.log(`MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`)
          message.close()
        }
      }
      fileReader.onerror = function () {
        this.error(`文件${file.name}读取出错，请检查该文件`)
        message.close()
        file.cancel()
      }
      function loadNext() {
        let start = currentChunk * chunkSize
        let end = start + chunkSize >= file.size ? file.size : start + chunkSize
        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end))
      }
    },
    //  计算MD5成功
    computeMD5Success(md5, file) {
      file.uniqueIdentifier = md5 // 把md5值作为文件的识别码
      file.resume() // 开始上传
    },
  },
}
